// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`adder.js 1`] = `
// @flow

function f(x : $Tainted<number>, y : $Tainted<number>) {
  var z : $Tainted<number> = x + y;
}
function f1(x : $Tainted<number>, y : number) {
  var z : $Tainted<number> = x + y;
}
function f2(x : number, y : $Tainted<number>) {
  var z : $Tainted<number> = x + y;
}
// This should cause an error.
function f3(x : $Tainted<number>, y : number) {
  var z : number = x + y;
}
// This should cause an error.
function f4(x : number, y : $Tainted<number>) {
  var z : number = x + y;
}
// This should cause an error.
function f5(x : number, y : $Tainted<number>) {
  var z : string = x + y;
}
// This should cause an error.
function f6(x : string, y : $Tainted<number>) {
  var z : string = x + y;
}
// This should cause an error.
function f7(x : $Tainted<string>, y : $Tainted<number>) {
  var z : string = x + y;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

function f(x: $Tainted<number>, y: $Tainted<number>) {
  var z: $Tainted<number> = x + y;
}
function f1(x: $Tainted<number>, y: number) {
  var z: $Tainted<number> = x + y;
}
function f2(x: number, y: $Tainted<number>) {
  var z: $Tainted<number> = x + y;
}
// This should cause an error.
function f3(x: $Tainted<number>, y: number) {
  var z: number = x + y;
}
// This should cause an error.
function f4(x: number, y: $Tainted<number>) {
  var z: number = x + y;
}
// This should cause an error.
function f5(x: number, y: $Tainted<number>) {
  var z: string = x + y;
}
// This should cause an error.
function f6(x: string, y: $Tainted<number>) {
  var z: string = x + y;
}
// This should cause an error.
function f7(x: $Tainted<string>, y: $Tainted<number>) {
  var z: string = x + y;
}

`;

exports[`any_object.js 1`] = `
// @flow

let tests = [
  // setting a property
  function(x: $Tainted<string>, y: string) {
    let obj: Object = {};
    obj.foo = x; // error, taint ~> any
    obj[y] = x; // error, taint ~> any
  },

  // getting a property
  function() {
    let obj: Object = { foo: 'foo' };
    (obj.foo: $Tainted<string>); // ok
  },

  // calling a method
  function(x: $Tainted<string>) {
    let obj: Object = {};
    obj.foo(x); // error, taint ~> any

    let foo = obj.foo;
    foo(x); // error, taint ~> any
  },
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

let tests = [
  // setting a property
  function(x: $Tainted<string>, y: string) {
    let obj: Object = {};
    obj.foo = x; // error, taint ~> any
    obj[y] = x; // error, taint ~> any
  },

  // getting a property
  function() {
    let obj: Object = { foo: "foo" };
    (obj.foo: $Tainted<string>); // ok
  },

  // calling a method
  function(x: $Tainted<string>) {
    let obj: Object = {};
    obj.foo(x); // error, taint ~> any

    let foo = obj.foo;
    foo(x); // error, taint ~> any
  }
];

`;

exports[`call-object-property.js 1`] = `
// @flow

function foo(x : $Tainted<string>, o : Object) {
  // Error
  o.f(x);
}
function foo1(x : $Tainted<string>, o : {f : (y : $Tainted<string>) => void}) {
  o.f(x);
}
function foo2(o1 : Object, o2 : {t : $Tainted<string>}) {
  o1.f(o2.t);
}
function foo3<T>(x : $Tainted<T>, o : {f : (y : $Tainted<T>) => void}) {
  o.f(x);
}
function f_foo1(x : $Tainted<string>, f : Function) {
  // Error
  f(x);
}
function f_foo2(f1 : Function, o : {t : $Tainted<string>}) {
  f1(o.t);
}
function f_foo3(f1 : Function, o1 : Object, o2 : {t : $Tainted<string>}) {
  (f1(o1))(o2.t);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

function foo(x: $Tainted<string>, o: Object) {
  // Error
  o.f(x);
}
function foo1(x: $Tainted<string>, o: { f: (y: $Tainted<string>) => void }) {
  o.f(x);
}
function foo2(o1: Object, o2: { t: $Tainted<string> }) {
  o1.f(o2.t);
}
function foo3<T>(x: $Tainted<T>, o: { f: (y: $Tainted<T>) => void }) {
  o.f(x);
}
function f_foo1(x: $Tainted<string>, f: Function) {
  // Error
  f(x);
}
function f_foo2(f1: Function, o: { t: $Tainted<string> }) {
  f1(o.t);
}
function f_foo3(f1: Function, o1: Object, o2: { t: $Tainted<string> }) {
  f1(o1)(o2.t);
}

`;

exports[`comparator.js 1`] = `
// @flow
// Should cause an error.
function f(x : $Tainted<string>, y : $Tainted<number>) {
  var z : $Tainted<bool> = x < y;
}
// Should cause an error.
function f1(x : string, y : $Tainted<number>) {
  var z : $Tainted<bool> = x < y;
}
// Should cause an error.
function f2(x : $Tainted<string>, y : number) {
  var z : $Tainted<bool> = x < y;
}
// Note: We allow removing Taint when two tainted
// values are compared.
function f3(x : $Tainted<string>, y : string) {
  var z : bool = x < y;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow
// Should cause an error.
function f(x: $Tainted<string>, y: $Tainted<number>) {
  var z: $Tainted<boolean> = x < y;
}
// Should cause an error.
function f1(x: string, y: $Tainted<number>) {
  var z: $Tainted<boolean> = x < y;
}
// Should cause an error.
function f2(x: $Tainted<string>, y: number) {
  var z: $Tainted<boolean> = x < y;
}
// Note: We allow removing Taint when two tainted
// values are compared.
function f3(x: $Tainted<string>, y: string) {
  var z: boolean = x < y;
}

`;

exports[`function.js 1`] = `
// @flow

let tests = [
  // flows any to each param
  function(x: any, y: $Tainted<string>) {
    x(y); // error, taint ~> any
  },

  // calling \`any\` returns \`any\`
  function(x: any, y: $Tainted<string>) {
    let z = x();
    z(y);
  }
];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

let tests = [
  // flows any to each param
  function(x: any, y: $Tainted<string>) {
    x(y); // error, taint ~> any
  },

  // calling \`any\` returns \`any\`
  function(x: any, y: $Tainted<string>) {
    let z = x();
    z(y);
  }
];

`;

exports[`globals.js 1`] = `
// @flow

class A {
  f(x : $Tainted<FakeLocation>) {
    fakeDocument.location = x; // error
    doStuff(x); // ok
  }
  f1(x : $Tainted<FakeLocation>) {
    // TODO(rcastano): should cause an error.
    window.fakeLocation = x;
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// @flow

class A {
  f(x: $Tainted<FakeLocation>) {
    fakeDocument.location = x; // error
    doStuff(x); // ok
  }
  f1(x: $Tainted<FakeLocation>) {
    // TODO(rcastano): should cause an error.
    window.fakeLocation = x;
  }
}

`;

exports[`lib.js 1`] = `
declare class FakeLocation {
  assign(url: string): void;
}

declare class FakeDocument {
  location: FakeLocation;
}

declare function doStuff(x: $Tainted<any>): void;

declare var fakeDocument: FakeDocument;
declare var fakeLocation: FakeLocation;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
declare class FakeLocation {
  assign(url: string): void;
}

declare class FakeDocument {
  location: FakeLocation;
}

declare function doStuff(x: $Tainted<any>): void;

declare var fakeDocument: FakeDocument;
declare var fakeLocation: FakeLocation;

`;

exports[`taint1.js 1`] = `
/*
 *
 * @flow
 */
class A {
  f(tainted : $Tainted<string>) {
    // This shouldn't give a warning (both are tainted)
    var also_tainted : $Tainted<string> = tainted;
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 *
 * @flow
 */
class A {
  f(tainted: $Tainted<string>) {
    // This shouldn't give a warning (both are tainted)
    var also_tainted: $Tainted<string> = tainted;
  }
}

`;

exports[`taint2.js 1`] = `
/*
 *
 * @flow
 */
class A {
  f(tainted : $Tainted<string>) {
    // This *should* give a warning.
    fakeDocument.location.assign(tainted);
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 *
 * @flow
 */
class A {
  f(tainted: $Tainted<string>) {
    // This *should* give a warning.
    fakeDocument.location.assign(tainted);
  }
}

`;

exports[`taint3.js 1`] = `
/*
 *
 * @flow
 */
class A {
  f(tainted : $Tainted<string>) {
    // The Tainted annotation should still flow.
    var safe = tainted;
    // This should give a warning.
    var loc : string = safe;
  }
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 *
 * @flow
 */
class A {
  f(tainted: $Tainted<string>) {
    // The Tainted annotation should still flow.
    var safe = tainted;
    // This should give a warning.
    var loc: string = safe;
  }
}

`;

exports[`taint4.js 1`] = `
/*
 *
 * @flow
 */

var safe : string = "safe";
// This should be allowed.
var tainted : $Tainted<string> = safe

function f(x : $Tainted<any>) {
  // Should cause error.
  var y : any = x;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 *
 * @flow
 */

var safe: string = "safe";
// This should be allowed.
var tainted: $Tainted<string> = safe;

function f(x: $Tainted<any>) {
  // Should cause error.
  var y: any = x;
}

`;

exports[`use-types.js 1`] = `
/*
 * @flow
 */

// Should cause an error.
function foo (x : $Tainted<number>) {
  var should_fail : number = x * 42;
}
// Should cause an error.
function foo1 (x : $Tainted<{f: number}>) {
  var ok : number = x.f;
}
// Should cause an error.
function foo2 (o : {f (y:number):number}, t: $Tainted<number>) {
  return o.f(t);
}

function foo3 (x : $Tainted<{f: number}>) {
  var also_tainted : $Tainted<number> = x.f;
}
// Should cause an error.
function foo4 (a : $Tainted<Array<string>>) {
  var trusted : string = a[0];
}
// Type error.
function foo5 (a : $Tainted<Array<string>>) {
  var trusted_number : number = a[0];
}

function foo6 (a : $Tainted<Array<string>>) {
  var trusted : $Tainted<string> = a[0];
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
 * @flow
 */

// Should cause an error.
function foo(x: $Tainted<number>) {
  var should_fail: number = x * 42;
}
// Should cause an error.
function foo1(x: $Tainted<{ f: number }>) {
  var ok: number = x.f;
}
// Should cause an error.
function foo2(o: { f(y: number): number }, t: $Tainted<number>) {
  return o.f(t);
}

function foo3(x: $Tainted<{ f: number }>) {
  var also_tainted: $Tainted<number> = x.f;
}
// Should cause an error.
function foo4(a: $Tainted<Array<string>>) {
  var trusted: string = a[0];
}
// Type error.
function foo5(a: $Tainted<Array<string>>) {
  var trusted_number: number = a[0];
}

function foo6(a: $Tainted<Array<string>>) {
  var trusted: $Tainted<string> = a[0];
}

`;
